package cn.flying.cloud.flow.core.listener.event;

import javax.annotation.Resource;

import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventType;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
import org.flowable.engine.delegate.event.FlowableActivityEvent;
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
import org.flowable.engine.delegate.event.FlowableMultiInstanceActivityEvent;
import org.flowable.engine.delegate.event.FlowableProcessStartedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import cn.flying.cloud.base.common.exception.BizException;
import cn.flying.cloud.flow.core.listener.enums.FlowableEventTypeEnum;
import cn.flying.cloud.flow.core.listener.event.callback.EventListenerCallback;

/**
 * 全局事件监听
 * <p>
 * 在 Flowable 中，FlowableEventListener、ExecutionListener 和 TaskListener 都是用来监听流程引擎中的不同类型的事件的接口，但它们的作用范围和使用场景有所不同。下面是这三个监听器的简要说明：
 * <p>
 * FlowableEventListener
 * 作用范围：全局级别。
 * 监听对象：可以监听整个流程引擎中发生的事件，比如流程实例的创建、启动、结束等。
 * 配置方式：通常通过流程引擎配置来设置，可以在 Spring 配置文件中定义或者通过编程方式添加到 ProcessEngineConfiguration 中。
 * 用途：适合用于需要跨多个流程或任务执行相同操作的情况，例如记录日志、发送通知等。
 * ExecutionListener
 * 作用范围：流程实例级别。
 * 监听对象：与流程实例的生命周期相关联，如开始一个流程、结束一个流程、进入一个活动节点（用户任务、服务任务等）时触发。
 * 配置方式：直接在 BPMN 2.0 文件中定义，通常是作为某个特定活动或流程元素的一部分。
 * 用途：适用于需要对流程执行过程中的某些特定阶段进行自定义处理的情况，比如在执行某个任务之前或之后执行额外的业务逻辑。
 * TaskListener
 * 作用范围：任务级别。
 * 监听对象：与任务的生命周期相关联，如创建任务、分配任务、完成任务等。
 * 配置方式：同样是在 BPMN 2.0 文件中定义，绑定到具体的任务上。
 * 用途：适合用来处理与任务相关的事件，例如在任务创建时自动分配给某人，在任务完成时更新数据库等
 *
 * @author: admin
 * @date: 2024年09月19日 17:40
 * @version: 1.0
 */
@Component
public class GlobalEventListenerHandler extends AbstractFlowableEngineEventListener {

    @Resource
    private ApplicationContext context;

    /**
     * @param event
     */
    @Override
    protected void taskCreated(FlowableEngineEntityEvent event) {
        callback(event);
    }

    /**
     * @param event
     */
    @Override
    protected void taskAssigned(FlowableEngineEntityEvent event) {
        callback(event);
    }

    /**
     * @param event
     */
    @Override
    protected void taskCompleted(FlowableEngineEntityEvent event) {
        callback(event);
    }

    /**
     * @param event
     */
    @Override
    protected void activityStarted(FlowableActivityEvent event) {
        callback(event);
    }

    /**
     * @param event
     */
    @Override
    protected void activityCompleted(FlowableActivityEvent event) {
        callback(event);
    }

    /**
     * @param event
     */
    @Override
    protected void multiInstanceActivityStarted(FlowableMultiInstanceActivityEvent event) {
        callback(event);
    }

    /**
     * @param event
     */
    @Override
    protected void processCreated(FlowableEngineEntityEvent event) {
        callback(event);
    }

    /**
     * @param event
     */
    @Override
    protected void processStarted(FlowableProcessStartedEvent event) {
        callback(event);
    }

    /**
     * @param event
     */
    @Override
    protected void processCompleted(FlowableEngineEntityEvent event) {
        callback(event);
    }

    /**
     * @param event
     */
    @Override
    protected void processCancelled(FlowableCancelledEvent event) {
        callback(event);
    }

    /**
     * @param event
     */
    @Override
    protected void jobExecutionFailure(FlowableEngineEntityEvent event) {
        callback(event);
    }

    /**
     * 回调处理
     *
     * @param event
     */
    private void callback(FlowableEvent event) {
        FlowableEventType type = event.getType();
        FlowableEventTypeEnum eventTypeEnum = FlowableEventTypeEnum.valueOf(type.name());
        if (eventTypeEnum == null) {
            throw new BizException("没有找到对应【{" + type + "}】事件的监听回调处理");
        }
        EventListenerCallback bean = (EventListenerCallback) context.getBean(eventTypeEnum.getClazz());
        bean.execute(event);
    }

    /**
     * @return
     */
    @Override
    public boolean isFailOnException() {
        // 如果为 true，当监听器抛出异常时，会停止流程执行
        return super.isFailOnException();
    }


}
